﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using EntityFrameworkContrib.PostSharp4EF;

namespace EFContrib.PS4EF.Tst.RelationShipType
{
    /// <summary>
    /// Summary description for RelationShipTest
    /// </summary>
    [TestClass]
    public class RelationShipTest
    {
        #region setup
        public RelationShipTest()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion


        #endregion

        /// <summary>
        /// Clears the customers.
        /// Not implemented as a testinitialization, because there are many tests
        /// here that do not hit the database
        /// </summary>
        void ClearCustomers()
        {
            using (SimpleRelationshipTestEntities context = new SimpleRelationshipTestEntities())
            {
                // clear out database
                foreach (Customer old in context.Customer)
                {
                    context.DeleteObject(old);
                }

                context.SaveChanges();
            }
        } 

        [TestMethod]
        public void testRelationShip()
        {
            Customer c = new Customer { Name = "Ruurd Boeke" };
            Car car = new Car { Make = "Ferrari" };
            Order o1 = new Order { Amount = 10 };
            Order o2 = new Order { Amount = 20 };

            car.Customer = c;

            Assert.AreEqual(c, car.Customer);
            Assert.AreEqual(c.Cars.First(), car);

            // add customer on order
            o1.Customer = c;
            // add order on customer, new way
            c.Orders.Add(o2);

            Assert.IsTrue(c.Orders.Count() == 2);
        }

        [TestMethod]
        public void testCanReAssignRelation()
        {
            Car car = new Car { Make = "Ferrari" };
            Customer c1 = new Customer { Name = "Ruurd Boeke" };
            Customer c2 = new Customer { Name = "Lucky Joe" };

            car.Customer = c1;

            // test is code is in place to actually remove the old customer and replace with the new one
            car.Customer = c2;

            Assert.AreEqual(car.Customer, c2);
        }

        [TestMethod]
        public void testImplementedAssemblyLevelAttributes()
        {
            object[] attributes = this.GetType().Assembly.GetCustomAttributes(false);

            // the edmschema attribute was created
            Assert.IsNotNull(attributes.FirstOrDefault(attr => attr is EdmSchemaAttribute));

            // relationship attribute was created
            Assert.IsNotNull(attributes.FirstOrDefault(attr => attr is EdmRelationshipAttribute));

        }

        [TestMethod]
        public void testImplementedRelationshipLoader()
        {
            Customer c = new Customer();
            IRelationshipLoader noLazyLoading = PostSharp.Post.Cast<Customer, IRelationshipLoader>(c);
        }

        [TestMethod]
        public void testRelationshipBreadth()
        {
            ClearCustomers();

            using (SimpleRelationshipTestEntities context = new SimpleRelationshipTestEntities())
            {
                Customer c = new Customer { Name = "Ruurd Boeke" };
                Customer c2 = new Customer { Name = "Test Customer" };
                Car car = new Car { Make = "Ferrari" };
                Car car2 = new Car { Make = "Porsche" };
                Order o1 = new Order { Amount = 10 };
                Order o2 = new Order { Amount = 20 };
                Order o3 = new Order { Amount = 30 };

                car.Customer = c;
                car.Customer = c2;  // can re assign test

                car2.Customer = c;

                // add customer on order
                o1.Customer = c;
                o2.Customer = c;
                // add order on customer, new way
                c.Orders.Add(o3);

                context.AddToCustomer(c);
                context.AddToCustomer(c2);
                context.SaveChanges();
            }

            using (SimpleRelationshipTestEntities context = new SimpleRelationshipTestEntities())
            {
                Customer c = context.Customer.First();

                IRelationshipLoader noLazyLoading = PostSharp.Post.Cast<Customer, IRelationshipLoader>(c);

                // load cars
                Assert.IsFalse(noLazyLoading.IsLoaded("Cars"));
                noLazyLoading.Load("Cars");

                Assert.IsTrue(noLazyLoading.IsLoaded("Cars"));
                Assert.IsTrue(c.Cars.Count == 1);

            }


        }

    }
}
